#include "drv_sdcard.h"
#include "bsp_sdmmc.h"
#if (CONFIG_OS_ENABLE == 1)
#include "os_sal.h"
#endif

/* SD(TF)-Card 内存卡 */

/* define */

#define sdcard_io_lock()        bsp_sdmmc2_lock()
#define sdcard_io_unlock()      bsp_sdmmc2_unlock()


/* static var */
//需要用到该数组,确保数据缓存区地址是4字节对齐的.
// static ALIGN(4) uint8_t sdcard_data_buffer[512];		



/* static func */


/* export func */

/**
 * @brief 初始化
 * 
 */
void drv_sdcard_init(void)
{
    bsp_sdmmc2_init();

}

/**
 * @brief 去初始化
 * 
 */
void drv_sdcard_deinit(void)
{
    bsp_sdmmc2_deinit();
}

/**
 * @brief SD卡是否插入(通过卡座的CD脚电平确定)
 * 
 * @return uint8_t 
 */
uint8_t drv_sdcard_is_exist(void)
{
    return bsp_sdmmc2_is_exist();
}


/**
 * @brief 获取内存卡信息
 * 
 * @param info 
 * @return uint8_t 
 */
uint8_t drv_sdcard_get_card_info(drv_sdcard_info_obj *info)
{
    if (info == NULL) return 1;    

    info->card_type =  bsp_sdmmc2_get_card_type();
    info->card_version = bsp_sdmmc2_get_card_version();
    info->card_speed = bsp_sdmmc2_get_card_speed();
    info->class = bsp_sdmmc2_get_class();
    info->rel_card_addr = bsp_sdmmc2_get_card_addr();
    info->block_nbr = bsp_sdmmc2_get_block_nbr();
    info->block_size = bsp_sdmmc2_get_block_size();
    info->block_logical_nbr = bsp_sdmmc2_get_block_logical_nbr();
    info->block_logical_size = bsp_sdmmc2_get_block_logical_size();

    return 0;
}

/**
 * @brief 获取内存卡CID信息
 * 
 * @param cid 
 * @return uint8_t 
 */
uint8_t drv_sdcard_get_card_cid(drv_sdcard_cid_obj *cid)
{
    cid->manufacturer_id = bsp_sdmmc2_get_manufacturer_id(); //制造商ID
    cid->oem_appli_id = bsp_sdmmc2_get_oem_appli_id();       //
    cid->prod_name_1 = bsp_sdmmc2_get_prod_name_1();
    cid->prod_name_2 = bsp_sdmmc2_get_prod_name_2();
    cid->prod_rev = bsp_sdmmc2_get_prod_rev();           //产品修订版
    cid->prod_sn = bsp_sdmmc2_get_prod_sn();             //产品序列号
    cid->manufact_date = bsp_sdmmc2_get_manufact_date(); //制造日期

    return 0;   
}


/**
 * @brief 获取当前SD卡状态
 * 
 * @return uint8_t 
 */
uint8_t drv_sdcard_get_state(void)
{
    HAL_SD_CardStateTypedef sta;
    uint8_t ret;

    sdcard_io_lock();
    sta = (HAL_SD_CardStateTypedef)bsp_sdmmc2_get_card_state();
    sdcard_io_unlock();
    switch (sta)
    {
    case HAL_SD_CARD_READY: ret = SDCARD_STA_READY; break;
    case HAL_SD_CARD_IDENTIFICATION: ret = SDCARD_STA_IDENTIFICATION; break;
    case HAL_SD_CARD_STANDBY: ret = SDCARD_STA_STANDBY; break;
    case HAL_SD_CARD_TRANSFER: ret = SDCARD_STA_TRANSFER; break;
    case HAL_SD_CARD_SENDING: ret = SDCARD_STA_SENDING; break;
    case HAL_SD_CARD_RECEIVING: ret = SDCARD_STA_RECEIVING; break;
    case HAL_SD_CARD_PROGRAMMING: ret = SDCARD_STA_PROGRAMMING; break;
    case HAL_SD_CARD_DISCONNECTED: ret = SDCARD_STA_DISCONNECTED; break;
    default: ret = SDCARD_STA_ERROR; break;
    }
    return ret;
}

/**
 * @brief SD卡擦除
 * 
 * @param addr_start 开始地址 
 * @param addr_end 结束地址
 * @return uint8_t 
 */
uint8_t drv_sdcard_erase(uint32_t addr_start, uint32_t addr_end)
{
    uint8_t sta;

    sdcard_io_lock();
    sta = bsp_sdmmc2_erase(addr_start, addr_end);
    sdcard_io_unlock();
    if (sta)
    {
        return 1;
    }
    return 0;
}

/**
 * @brief SD卡读取数据
 * 
 * @param addr 扇区地址
 * @param pbuf 读取缓存
 * @param blocks 扇区个数
 * @param timeout 超时时间(ms)
 * @return uint8_t 0,OK
 */
uint8_t drv_sdcard_read_blocks(uint32_t addr, uint8_t *pbuf, uint32_t blocks, uint32_t timeout)
{
    uint8_t sta;

    // system_int_disable();
    sdcard_io_lock();
    sta = bsp_sdmmc2_read(addr, (uint8_t*)pbuf, blocks, timeout);
    sdcard_io_unlock();

    while (drv_sdcard_get_state() != SDCARD_STA_TRANSFER)
    {
        if (timeout == 0)
        {
            sta = HAL_ERROR;
            break;
        }
        timeout--;
    }

    // system_int_enable();

    if (sta != HAL_OK)
    {
        return 1;
    }
    return 0;
}

/**
 * @brief SD卡写入数据
 * 
 * @param addr 扇区地址
 * @param pbuf 写入缓存
 * @param blocks 扇区个数
 * @param timeout 超时时间(ms)
 * @return uint8_t 0,OK
 */
uint8_t drv_sdcard_write_blocks(uint32_t addr, uint8_t *pbuf, uint32_t blocks, uint32_t timeout)
{
    uint8_t sta;

    sdcard_io_lock();
    sta = bsp_sdmmc2_write(addr, (uint8_t*)pbuf, blocks, timeout);
    sdcard_io_unlock();
    if (sta)
    {
        return 1;
    }
    return 0;
}


uint8_t drv_sdcard_read_blocks_dma(uint32_t addr, uint32_t *pbuf, uint32_t blocks)
{
    uint8_t sta;

    sdcard_io_lock();
    sta =  bsp_sdmmc2_read_blocks_dma(addr, pbuf, blocks);
    sdcard_io_unlock();
    return sta;
}

uint8_t drv_sdcard_write_blocks_dma(uint32_t addr, uint32_t *pbuf, uint32_t blocks)
{
    uint8_t sta;

    sdcard_io_lock();
    sta =  bsp_sdmmc2_write_blocks_dma(addr, pbuf, blocks);
    sdcard_io_unlock();
    return sta;
}




/* Callback in non blocking modes (DMA) */
// void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd);
// void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd);
// void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd);
// void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd);


